package no.niths.infrastructure; import java.util.List; import no.niths.domain.Domain; import no.niths.infrastructure.interfaces.GenericRepository; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.SessionFactory; import org.hibernate.criterion.Example; import org.hibernate.criterion.MatchMode; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; /** * Abstract generic repository class that generates all the basic CRUD actions * for repository classes. * <p> * How to use: * <p> * First create an interface that defines the methods. Naming is important for * the code to be easy to read, so call it YourDomainRepository. * <p> * If you keep the interface empty, it will give you the basic CRUD methods: * create, update, delete, getById and getAll * <p> * Then create a new class that implements the interface and, extends this class * like this (Remember naming convention): * <p> * * <pre> * {@code * Repository * public class YourDomainRepositoryImpl extends AbstractGenericRepositoryImpl<YourDomain> * implements YourDomainRepository{ * * public YourDomainRepositoryImpl() { * super(YourDomain.class, new YourDomain()); * } * * } * } * * </pre> * * @param <T> */ public abstract class AbstractGenericRepositoryImpl<T extends Domain> implements GenericRepository<T> { private Class<T> persistentClass; private Domain domain; /** * Constructor takes the persistence class and the persistence domain * <p> * * @param persistentClass * the domain class * @param domain * an empty object of your domain type */ public AbstractGenericRepositoryImpl(Class<T> persistentClass, Domain domain) { this.persistentClass = persistentClass; this.domain = domain; } @Autowired private SessionFactory session; /** * Persist a provided domain * <p> * * @param domain * the object you want to persist * @return id of the domain */ @Transactional(readOnly = false) public Long create(T domain) { return (Long) session.getCurrentSession().save(domain); } /** * Find and returns all objects which has values equal to the object sent as * parameter. * * @param domain * - The object that has the values to search for * @return List of objects found */ @SuppressWarnings("unchecked") public List<T> getAll(T domain) { return buildCriteria(domain, MatchMode.ANYWHERE).list(); } /** * Find and returns all objects which has values equal to the object sent as * parameter. * <p> * Supports pagination * <p> * * @param domain * the object that has the values to search for * @param firstResult * the first result * @param maxResults * number of results in the returning list * @return List of objects found */ @SuppressWarnings("unchecked") public List<T> getAll(T domain, int firstResult, int maxResults) { return (List<T>) buildCriteria(domain, MatchMode.ANYWHERE) .setFirstResult(firstResult).setMaxResults(maxResults).list(); } /** * Helper method for creating criteria * @param domain * @param matchMode * @return */ private Criteria buildCriteria(T domain, MatchMode matchMode) { Criteria criteria = session.getCurrentSession().createCriteria( persistentClass); if (domain != null) { criteria.add(Example.create(domain).enableLike(matchMode)); } return criteria; } /** * Returns a domain on a given id * @param id * @return the domain with matching ID, or null if not found */ @SuppressWarnings("unchecked") public T getById(long id) { return (T) session.getCurrentSession().get(persistentClass, id); } /** * Updates a existing domain * <p> * * @param domain * the object */ @Transactional(readOnly = false) public void update(T domain) { session.getCurrentSession().update(domain); } /** * Deletes a domain on a given id * * @param id * @return true if update succeeded, false otherwise */ @Transactional(readOnly = false) public boolean delete(long id) { Query query = session.getCurrentSession() .createQuery( "delete " + persistentClass.getSimpleName() + " where id = :id"); query.setParameter("id", id); return (1 == query.executeUpdate()); } /** * Deletes a domain on a given id and deletes relationships. * * @param id * the id of the object to delete */ public void hibernateDelete(long id) { domain.setId(id); getSession().getCurrentSession().delete(domain); } /** * Returns a instance of the persistence class * * @return */ public Class<T> getPersistentClass() { return persistentClass; } /** * Returns the given session * * @return session */ public SessionFactory getSession() { return session; } }